package com.attilax.linq;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import aaaCfg.IocX4nodb;
// r3 26 import aaaDbManager.DbMetaService;

import com.attilax.Stream.Mapx;
import com.attilax.biz.seo.getConnEx;
import com.attilax.db.DBX;
import com.attilax.lang.MapX;
import com.attilax.lang.text.strUtil;
import com.attilax.sql.DbMetaService;
import com.attilax.util.mapUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Inject;

public class LinqBuilder   {

	@Inject
	DBX dbx;
	protected Object table;
	private int limit;
	protected String op;
	AExpression whereExpressAst;

	public static EqExpression eq(String string, Object v) {
		// TODO Auto-generated method stub
		return new EqExpression(string, v);
	}

	public static LikeExpression like(String col, String val) {
		// TODO Auto-generated method stub
		LikeExpression le = new LikeExpression(col, val);
		// if(whereExpressAst==null)

		return le;
	}

	public static LinqBuilder from(List  table) {
		LinqBuilder lb = new LinqBuilder();
		lb.table = table;
		lb.op = "select";
		return lb;

	}
	
//	public static LinqBuilder from(List  table) {
//		LinqBuilder lb = new LinqBuilder();
//		lb.table = table;
//		lb.op = "select";
//		return lb;
//
//	}

	public static LinqBuilder from(String table) {

		LinqBuilder lb = IocX4nodb.getBean(LinqBuilder.class);
		lb.table = table;
		lb.op = "select";
		return lb;

	}

	public static LinqBuilder updateTable(String table) {
		// TODO Auto-generated method stub

		LinqBuilder lb = IocX4nodb.getBean(LinqBuilder.class);
		lb.table = table;
		lb.op = "update";
		return lb;
	}

	public LinqBuilder set(String string, Object cates) {
		this.setKv.put(string, cates);
		return this;
	}

	public static Map FuncCustoms = Maps.newLinkedHashMap();

	public static Object invokeFun(String fun, Object... col) {
		// TODO Auto-generated method stub
		CustomFun cf = (CustomFun) LinqBuilder.FuncCustoms.get(fun);
		cf.fld = col;

		return cf;
	}

	public LinqBuilder where() {
		// TODO Auto-generated method stub
		return this;
	}

	public Map<String, Object> setKv = Maps.newLinkedHashMap();
	private Object priKey;
	@Inject
	DbMetaService dms;

	public List<Map> exe() {
		
		
		if(this.table instanceof List)
		{
			return new LinqBuilder4List(this.table,this.op,this.whereExpressAst).exe();
		}

		if (this.op.equals("update"))
			return (List<Map>) extUpdateOp();

		String sql = "select * from " + table + " limit "
				+ String.valueOf(this.limit);
		List<Map> li = dbx.executeQuery(sql);
		if (this.selectCols == null)
			return li;

		List<Map> rzt_li = Lists.newArrayList();
		for (Object col : selectCols) {
			if (col instanceof reduceFun) {

				String reduceVal = "";
				for (Map map : li) {
					try {
						this.curRow = map;
						CustomFun cf = (CustomFun) col;
						// cf.row=
						List<Object> flds = Arrays.asList(cf.fld);
						List<Object> vs = getVals(flds);
						vs.add(reduceVal);
						reduceVal = (String) cf.ext(vs);

					} catch (Exception e) {
						e.printStackTrace();
					}

				}
				Map m = Maps.newLinkedHashMap();
				m.put("xxx", reduceVal);
				rzt_li.add(m);
			}
		}

		return rzt_li;
		// TODO Auto-generated method stub

	}

	private Object extUpdateOp() {
		try {
			this.priKey = dms.getPrimaryKeys(dbx.getConnection(), this.table);
		} catch (getConnEx e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		String sql = "select * from " + table + this.whereStr + " limit "
				+ String.valueOf(this.limit);
		List<Map> li = dbx.executeQuery(sql);
		List<Map> rzt_li = Lists.newArrayList();
		for (Map map : li) {
			try {
				this.curRow = map;
				String sq = this.op + " " + this.table + " set "
						+ getKvStrSqlFmt() + " where " + this.priKey + "="
						+ map.get(this.priKey) + "  ";
				System.out.println(sq);
				int rzt = dbx.execSql_retInt(sq);
				Map m = Maps.newLinkedHashMap();
				m.put("sql", sq);
				m.put("rzt", rzt);
				rzt_li.add(m);
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		return rzt_li;
	}

	private Object getPrikey() {
		// TODO Auto-generated method stub
		return null;
	}

	public Map curRow;
	private Object[] selectCols;
	private String whereStr = " where 1=1 ";

	private String getKvStrSqlFmt() {
		String s = "";
		Set<String> st = setKv.keySet();
		for (String col : st) {
			Object v = setKv.get(col);
			String newVal = "";
			if (v instanceof CustomFun) {
				CustomFun cf = (CustomFun) v;
				// cf.row=
				List<Object> flds = Arrays.asList(cf.fld);
				List<Object> vs = getVals(flds);
				newVal = (String) cf.ext(vs);
			} else
				newVal = (String) v;
			s = s + "," + col + "='" + newVal + "'";
		}
		s = strUtil.trimx(",", s);
		return s;
	}

	private List<Object> getVals(List<Object> flds) {

		List<Object> rzt = Lists.newArrayList();
		for (Object col : flds) {
			rzt.add(curRow.get(col));
		}
		// TODO Auto-generated method stub
		return rzt;
	}

	public LinqBuilder where(Object objesct) {

		if (objesct instanceof AExpression) {
			if (whereExpressAst == null)
				whereExpressAst = (AExpression) objesct;
		} else if (objesct != null && objesct.toString().trim().length() > 3)
			this.whereStr = whereStr + " and " + objesct.toString();

		return this;
	}

	public LinqBuilder limit(int i) {
		// TODO Auto-generated method stubthhis.
		this.limit = i;
		return this;
	}

	public LinqBuilder select(Object... selectCols) {
		this.selectCols = selectCols;

		return this;
	}

	public LinqBuilder and(AExpression eq) {
		if(whereExpressAst==null)
			whereExpressAst=eq;
		else
		{
			AndExpression ae=new AndExpression(whereExpressAst,eq);
			whereExpressAst=ae;
		}
		
		return this;
	}

	public LinqBuilder orderby() {
		// TODO Auto-generated method stub
		return null;
	}

}
